package com.mojo.concurrent.concurrent_04_cas_atomic;

import java.util.LinkedList;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.concurrent.atomic.AtomicReference;

/**
 * CAS ABA问题,此示例不太好，后续修改
 *
 * @author <a href="mailto:mojo_jj@163.com">Mojo</a>
 */
public class CasDemo02 {
    public static void main(String[] args) throws InterruptedException {
        LinkedList<Node> queue = new LinkedList<>();
        Node a = new Node("A");
        Node b = new Node("B");
        queue.add(b);
        queue.add(a);
        AtomicReference<Node> reference = new AtomicReference<>();
        reference.set(a);
        Thread t1 = new Thread(() -> {
            try {
                Node old = reference.get();
                System.out.println("old:" + old);
                Thread.sleep(5000L);
                System.out.println("old == new Node : " + (old == new Node("A")));
                System.out.println("old == new Node : " + (Objects.equals(old, new Node("A"))));
                System.out.println(reference.compareAndSet(old, new Node("C")));
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        t1.start();
        Thread t2 = new Thread(() -> {
            //poll A B, push D  A
            System.out.println("B==>" + queue.poll());
            System.out.println("A==>" + queue.poll());
            queue.push(new Node("D"));
            queue.push(new Node("C"));
            queue.push(new Node("s"));

        });
        t2.start();
        t1.join();
        t2.join();
        System.out.println("queue ==>" + queue);
    }
}


class Node {
    String name;

    public Node(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Node node = (Node) o;
        return Objects.equals(name, node.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", Node.class.getSimpleName() + "[", "]")
                .add("name='" + name + "'")
                .toString();
    }
}